package main

import (
	"encoding/binary"
	"fmt"
	"net"
)

const (
	protocolVersion = 0x11
)

// Frame 定义了通信帧的结构。
type Frame struct {
	Header          uint16 // 帧头，固定值为 0xA55A
	Length          uint16 // 帧长度，包括帧头、帧长度、厂家编号、协议版本、帧类型、设备编号、数据和校验和
	ManufacturerID  uint8  // 厂家编号
	ProtocolVersion uint8  // 协议版本，当前值为 0x11
	FrameType       uint8  // 帧类型，表示帧的功能
	DeviceID        uint32 // 设备编号，唯一标识设备
	Data            []byte // 数据段，根据帧类型不同，数据内容不同
	Checksum        uint8  // 校验和，用于验证数据完整性
	Tail            uint32 // 帧尾，固定值为 0xCC33C33C
}

// parseFrame 将字节数组解析为 Frame 结构体，并验证校验和。
func parseFrame(data []byte) (*Frame, error) {
	if len(data) < 18 {
		return nil, fmt.Errorf("帧长度过短")
	}

	frame := &Frame{
		Header:          binary.BigEndian.Uint16(data[0:2]),
		Length:          binary.BigEndian.Uint16(data[2:4]),
		ManufacturerID:  data[4],
		ProtocolVersion: data[5],
		FrameType:       data[6],
		DeviceID:        binary.BigEndian.Uint32(data[7:11]),
		Data:            data[11 : len(data)-3],
		Checksum:        data[len(data)-3],
		Tail:            binary.BigEndian.Uint32(data[len(data)-2:]),
	}

	// 验证校验和
	checksum := uint8(0)
	for i := 0; i < len(data)-3; i++ {
		checksum += data[i]
	}
	if checksum != frame.Checksum {
		return nil, fmt.Errorf("校验和错误")
	}

	return frame, nil
}

// constructResponseFrame 根据给定的参数构造响应帧。
func constructResponseFrame(deviceID uint32, frameType uint8, data []byte) []byte {
	frame := &Frame{
		Header:          0xA55A,
		Length:          uint16(len(data) + 14),
		ManufacturerID:  0x00, // 替换为实际的厂家编号
		ProtocolVersion: protocolVersion,
		FrameType:       frameType,
		DeviceID:        deviceID,
		Data:            data,
		Checksum:        0x00, // 替换为计算出的校验和
		Tail:            0xCC33C33C,
	}

	// 计算校验和
	checksum := uint8(0)
	for i := 0; i < len(frame.Data)+11; i++ {
		checksum += frame.Data[i]
	}
	frame.Checksum = checksum

	return frame.Bytes()
}

// connectDevice 连接到设备并按照协议进行通信。
func connectDevice(deviceID uint32, ip string, port int) {
	conn, err := net.DialTCP("tcp", nil, &net.TCPAddr{IP: net.ParseIP(ip), Port: port})
	if err != nil {
		fmt.Printf("连接到设备 %d 失败: %s\n", deviceID, err)
		return
	}
	defer conn.Close()

	fmt.Printf("已连接到设备 %d\n", deviceID)

	// 发送注册请求帧
	registerFrame := constructResponseFrame(deviceID, 0x00, []byte{})
	conn.Write(registerFrame)

	// TODO: 实现其他通信逻辑
}

func main() {
	// 替换为实际的设备信息
	connectDevice(0x00000001, "192.168.1.100", 8080)
}
